﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Design;
using EnvDTE;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.Design.WebControls;
using System.Web.UI.WebControls;
using System.Reflection;
using System.Diagnostics;

namespace Catalyst.Web.DynamicData.Design
{
    public class UpgradeDataSourceDesignerActionList : DesignerActionList
    {
        private ProjectItem _page = null;
        private DataBoundControlDesigner _dataBoundControlDesigner;
        private WebFormsRootDesigner _formDesigner;
        private IDesignerHost _designerHost;

        public UpgradeDataSourceDesignerActionList(IComponent component, DataBoundControlDesigner dataBoundControlDesigner)
            : base(component)
        {
            _page = GetService(typeof(ProjectItem)) as ProjectItem;
            _dataBoundControlDesigner = dataBoundControlDesigner;
            GetFormsRootDesigner(component);
        }

        private void GetFormsRootDesigner(IComponent component)
        {
            _designerHost = (IDesignerHost)component.Site.GetService(typeof(IDesignerHost));
            if (_designerHost != null)
            {
                IComponent rootComponent = _designerHost.RootComponent;
                if (rootComponent != null)
                {
                    _formDesigner = _designerHost.GetDesigner(rootComponent) as WebFormsRootDesigner;
                }
            }
        }

        public override DesignerActionItemCollection GetSortedActionItems()
        {
            DesignerActionItemCollection items = new DesignerActionItemCollection();
            if(CanUpgradeDataSource)
                items.Add(new DesignerActionMethodItem(this, "UpgradeDataSource", "Upgrade DataSource", "Data Sources", "Upgrades the DataSource to a DynamicDataSource which allows complex filtering.", false));
            return items;
        }

        private bool CanUpgradeDataSource
        {
            get
            {
                if (string.IsNullOrEmpty(_dataBoundControlDesigner.DataSourceID))
                    return false;

                Control control = GetDataSource(_dataBoundControlDesigner.DataSourceID);
                if (control != null)
                {
                    if (control.GetType() == typeof(LinqDataSource))
                        return true;
                }

                return false;
            }
        }

        private Control GetDataSource(string dataSourceId)
        {
            Page page = _formDesigner.Component as Page;
            if (page != null)
            {
                return page.FindControl(dataSourceId);
            }
            return null;
        }

        public void UpgradeDataSource()
        {
            if (CanUpgradeDataSource)
            {
                ControlDesigner.InvokeTransactedChange(this.Component, this.UpdateDataSourceCallback, null, "Upgrade Datasource");
            }
        }

    private bool UpdateDataSourceCallback(object context)
    {
        try
        {
            string dataSourceId = _dataBoundControlDesigner.DataSourceID;
            Control oldDataSource = GetDataSource(dataSourceId);
            
            if (oldDataSource.GetType() == typeof(LinqDataSource))
            {
                DynamicLinqDataSource dynamicDataSource = new DynamicLinqDataSource();
                CopyProperties(oldDataSource, dynamicDataSource);
                dynamicDataSource.ID = "newDataSource";

                _formDesigner.AddControlToDocument(dynamicDataSource, oldDataSource, ControlLocation.After);

                PropertyDescriptor idProperty = TypeDescriptor.GetProperties(oldDataSource)["ID"];
                if (idProperty != null)
                    idProperty.SetValue(oldDataSource, "oldDataSource");

                _formDesigner.RemoveControlFromDocument(oldDataSource);

                idProperty = TypeDescriptor.GetProperties(dynamicDataSource)["ID"];
                if (idProperty != null)
                    idProperty.SetValue(dynamicDataSource, dataSourceId);
            }
        }
        catch(Exception ex)
        {
            System.Windows.Forms.MessageBox.Show(ex.ToString());
            return false;
        }
        return true;
    }

        //TODO: Clean this up! It's just lazy coding
        public void CopyProperties(Control source, Control destination)
        {
            foreach (PropertyInfo pi in source.GetType().GetProperties())
            {
                if (pi.CanWrite)
                {
                    try
                    {
                        var visibilityAttribute = (DesignerSerializationVisibilityAttribute)pi.GetCustomAttributes(typeof(DesignerSerializationVisibilityAttribute), true).FirstOrDefault();
                        if (visibilityAttribute == null || visibilityAttribute.Visibility != DesignerSerializationVisibility.Hidden)
                        {
                            pi.SetValue(destination, pi.GetValue(source, null), null);
                        }
                    }
                    catch { }
                }
            }
        }
    }
}
